/**
 * @fileoverview search.js
 * This file contains the search route for the server.
 */

// Express Router
const router = require("express").Router();

// Import Schema
const { SearchLaw, SearchLawItem } = require("../schema/searchSchema");
const { Law, LawItem } = require("../schema/lawSchema");
const {
  getSearchedRoots,
  formItemFilter,
  getSearchCondition,
  optionalParamValidity,
} = require("./utilities/searchUtil");

// 仅标题搜索
router.post("/search-title", async (request, response) => {
  const keywords = request.body.keywords;
  try {
    // 搜索到映射数据
    const searchResult = await SearchLaw.find(getSearchCondition(keywords), {
      score: { $meta: "textScore" },
    }).sort({ score: { $meta: "textScore" } });
    // 真实的文档数据
    const realDocuments = await Promise.all(
      searchResult.map(async (item) => {
        const document = await Law.findById(item.mapping);
        return document;
      })
    );
    const sortedData = realDocuments.sort((a, b) => {
      return String(a._id).localeCompare(String(b._id));
    });
    response.status(200).json(sortedData);
  } catch (err) {
    console.error(err);
  }
});

// 全文搜索 - 不包含高级搜索
router.post("/search-fulltext", async (request, response) => {
  // 检索的条件项
  const keywords = request.body.keywords;
  try {
    //搜索到映射数据
    const searchResult = await SearchLawItem.find(
      getSearchCondition(keywords),
      { score: { $meta: "textScore" } }
    ).sort({ score: { $meta: "textScore" } });
    const realDocuments = await Promise.all(
      searchResult
        .map(async (item) => {
          const document = await LawItem.findById(item.mapping);
          return document;
        })
        .sort((a, b) => {
          return String(a._id).localeCompare(String(b._id));
        })
    );

    const searchedRoots = await getSearchedRoots(realDocuments);
    // 响应数据
    const responseData = {
      searchedItem: realDocuments,
      searchedRoots: searchedRoots,
    };
    response.status(200).json(responseData);
  } catch (err) {
    console.error(err);
  }
});

// 高级搜索 API
router.post("/search-advanced-fulltext", async (request, response) => {
  try {
    const form = request.body.form;
    const filterCriteria = formItemFilter(form);
    const keywords = filterCriteria.keywords || filterCriteria.keyWords || "";
    delete (filterCriteria.keywords
      ? filterCriteria.keywords
      : filterCriteria.keyWords);
    const fulltext =
      filterCriteria.fulltext || filterCriteria.fullText || false;
    delete (filterCriteria.fulltext
      ? filterCriteria.fulltext
      : filterCriteria.fullText);
    let searchRes = [];
    let searchedRoots = {};

    // 获取搜索条件函数
    const getSearchResults = async (collection, condition, idsField = null) => {
      if (keywords.length === 0) {
        const res = await collection.find(condition).lean();
        return res;
      } else {
        const searchCondition = getSearchCondition(keywords, idsField);
        const res = await collection.find(searchCondition).lean();
        return res;
      }
    };

    console.log(filterCriteria);
    switch (fulltext) {
      case false:
        // 标题搜索
        {
          const laws = await SearchLaw.find(filterCriteria)
            .lean()
            .select("_id");
          const lawIds = laws.map((law) => law._id);
          // law模型没有索引
          const searchedLaws = await getSearchResults(
            SearchLaw,
            filterCriteria,
            lawIds
          );
          await Promise.all(
            searchedLaws.map(async (law) => {
              const relRes = await Law.findOne(law.mapping).lean();
              return (
                optionalParamValidity(form, relRes) && searchRes.push(relRes)
              );
            })
          );
          searchRes.sort((a, b) => {
            return String(a._id).localeCompare(String(b._id));
          });
        }

        break;
      case true:
        {
          const searchCondition = getSearchCondition(keywords);
          const searchedItems = await SearchLawItem.find(searchCondition)
            .sort({
              score: { $meta: "textScore" },
            })
            .lean()
            .select("mapping");

          const lawItemIds = searchedItems.map((item) => item.mapping);
          const realDocuments = await LawItem.find({
            _id: { $in: lawItemIds },
          }).lean();
          searchedRoots = await getSearchedRoots(realDocuments);
          // console.log(realDocuments);
          const rootsName = Object.keys(searchedRoots);
          await Promise.all(
            rootsName.map(async (rootName) => {
              const validItems = await Promise.all(
                searchedRoots[rootName].map(async (item) => {
                  const root = await Law.findById(
                    item[item.length - 1].parent
                  ).lean();
                  // console.log(root);
                  return optionalParamValidity(form, root) ? item[0] : null;
                })
              );
              searchRes.push(...validItems.filter(Boolean));
            })
          );
          // console.log(searchRes);
          searchRes = [...new Set(searchRes)];
          searchedRoots = await getSearchedRoots(searchRes);

          const laws = await Promise.all(
            rootsName.map(async (name) => {
              const law = await Law.findById(
                searchedRoots[name][0][searchedRoots[name][0].length - 1].parent
              );
              return law;
            })
          );
          searchedRoots = {
            ...searchedRoots,
            laws: laws.sort((a, b) => {
              return String(a._id).localeCompare(String(b._id));
            }),
          };
        }
        break;
      default:
        break;
    }
    // console.log({ searchRes, searchedRoots });
    response.status(200).json({ searchRes, searchedRoots });
  } catch (err) {
    console.error(err);
    response.status(500).json({ error: "Internal Server Error" });
  }
});

module.exports = router;
